package org.arclib.x.gui.widgets;

import java.awt.event.MouseEvent;

import org.apache.log4j.Logger;
import org.arclib.Font;
import org.arclib.math.Point;
import org.arclib.time.Blinker;
import org.arclib.x.gui.themes.Theme;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;


/// TextBox widget supports a single line of text only
public class TextBox extends Widget 
{
	public TextBox()
	{
		blink = new Blinker(); 
	}

	/// draw textfield 
	public void draw(Point parentPos)
	{
		Theme.theme.drawTextField(action, focus, position.add(parentPos), size, color); 
	}

	/// process textfield 
	public void process(Point parentPos)
	{
		if (blink == null)
		{
			log.fatal("Blinker needs to be initialized");
		}
		assert(blink != null); 
		
		super.process(parentPos);

		// INPUT BOX PROCESSING ////////////
		// blink every half second
		blink.process(.5); 

		if (focus)
		{
			// delete keys 
			if (Keyboard.isKeyDown(Keyboard.KEY_DELETE) || Keyboard.isKeyDown(Keyboard.KEY_BACK))
			{
				if (text.length() > 0)
				{
					// in middle of string 
					if (index < text.length() && index >= 0)
					{
						String newstr = text.toString();

						if (Keyboard.isKeyDown(Keyboard.KEY_DELETE))
						{
							text = newstr.substring(0 , index);
							text += newstr.substring(index+1 , newstr.length());	
	//							writefln("\ndel ", index);
						}
						else if (Keyboard.isKeyDown(Keyboard.KEY_BACK))
						{
							if (index >= 1)
							{
								text = newstr.substring(0 , index-1);
								text += newstr.substring(index , newstr.length());			
								index--; 
		//						writefln("\nmid back ", index); 
							}
						}
					}
					// at the end of the string 
					else if (!Keyboard.isKeyDown(Keyboard.KEY_DELETE))
					{

						text = text.substring(0 , text.length()-1);
						index--;
			//			writefln("\nback ", index); 
					}

				//	writefln(index); 
				//	writefln(text); 
				}
				//writefln("Index is ", index, " and str length is ", text.length); 
				//writefln(text); 
			}
			// add to string
			else if (Keyboard.isKeyDown(Keyboard.CHAR_NONE) && font.getWidth(text + " ") + parentPos.x + position.x < getWidth() + parentPos.x + position.x)// && font.getWidth(text) < getWidth + parentPos.x + position.x)
			{
					//writefln("Index is ", index, " and str length is ", text.length); 
					// insert characters at end of string
				
				// ignore newlines or return characters
				if (!Keyboard.isKeyDown(Keyboard.KEY_RETURN))
				{
					if (index == text.length())
					{
						text += Keyboard.getEventCharacter();  
						index += 1;//arc.input.lastChars.length; 
						//writefln(index); 
					}
					// insert characters inside of string
					else
					{
						text = insert(text, index, Keyboard.getEventCharacter()); 
						index += 1;//arc.input.lastChars.length; 
						//writefln(index); 
					}
				}
				//}
				
			//	writefln(text); 
			}

			if (Keyboard.isKeyDown(Keyboard.KEY_LEFT))
			{
				if (index > 0)
				{
					index--;
					//writefln(index); 
				}
			}

			
			if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT))
			{
				if (index < text.length())
				{
					index++;
					//writefln(index);
				}
			}
		}

		if (blink.on)
		{
			showcursor = !showcursor; 
		}

		//writefln("Showcursor is ", showcursor); 
		//writefln("Focus is ", focus); 
      
		// compute font x and y locations of the text
		Point targetPos = Point.Zero; 
		
		switch(alignment)
		{
			case LEFTCENTER:
			case LEFTUP:
			case LEFTDOWN: 
				targetPos = parentPos.add(fontAlign);
			break;
			
			case RIGHTCENTER:
			case RIGHTUP:
			case RIGHTDOWN:
				// re-calculate alignment every time
				targetPos = parentPos.add(getAlignment());
			break; 
			
			case CENTER:
			case CENTERUP:
			case CENTERDOWN:
				// re-calculate alignment every time
				targetPos = parentPos.add(getAlignment());
			break; 

			default:
				log.fatal("Alignment not set"); 
				assert(false); 
		}
	
		
		
		//Point targetPos = position + parentPos; 
		//targetPos.y += size.h/2 - font.getHeight/2; 
		
		if (showcursor && focus)
		{
			String cursortext = insert(text, index, "|");
			font.draw(targetPos, cursortext, fontColor);
		}
		else
		{
			font.draw(targetPos, text, fontColor); 
		}

		if (isMouseOver(parentPos) && Mouse.isButtonDown(MouseEvent.BUTTON1))
		{
			focus = true; 
		}
		else if (Mouse.isButtonDown(MouseEvent.BUTTON1))
		{
			focus = false; 
		}

		// mouse click
		if (Mouse.isButtonDown(MouseEvent.BUTTON1))
		{
			if (showcursor)
			{
				String cursortext = insert(text, index, "|");
				
				// subtract one because we add an extra character here
				index = font.calculateIndex(cursortext, targetPos, new Point(Mouse.getX(), Mouse.getY()))-1;
//				writefln("Calculate index is ", index); 
			}
			else
				index = font.calculateIndex(text, targetPos, new Point(Mouse.getX(), Mouse.getY()));

			if (index > text.length())
				index = text.length()-1;
			//if (index == 0) index = text.length-1;
		}

	}
	



	private String insert(String text, int index2, char eventCharacter)
	{
		return insert(text, index2, eventCharacter); 
	}

	private String insert(String s, int index, String sub)
	{
		assert(0 <= index && index <= s.length());
		
		if (sub.length() == 0)
			return s;

		if (s.length() == 0)
			return sub;

		String result =	null;
		
		result += s.substring(0, index); 
		result += sub; 
		result += s.substring(index, s.length());

		return result;
	}

	/// set text of widget 
	public void setText(String argText)
	{
		assert(font != null); 
		String[] lines = argText.split("\n");   
		
		if (lines.length > 1)
		{
			log.fatal("TextBox is single line only at the moment"); 
			assert(false); 
		}

		text = argText; 
	}

	/// set font and set widget size correctly
	public void setFont(Font argFont)
	{
		font = argFont; 
	}

	private final static Logger log = Logger.getLogger(TextBox.class); 
	Blinker blink; 
	boolean showcursor = false; 
	int index; 
}
